package com.store.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.store.dto.StockAdjustRequest;
import com.store.dto.StockQueryRequest;
import com.store.entity.Order;
import com.store.entity.Product;
import com.store.entity.StockRecord;
import com.store.entity.User;
import com.store.mapper.OrderMapper;
import com.store.mapper.ProductMapper;
import com.store.mapper.StockRecordMapper;
import com.store.mapper.UserMapper;
import com.store.vo.StockRecordVO;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 库存服务
 * 
 * @author Store Team
 */
@Service
@RequiredArgsConstructor
public class StockService {

    private final StockRecordMapper stockRecordMapper;
    private final ProductMapper productMapper;
    private final UserMapper userMapper;
    private final OrderMapper orderMapper;

    private static final Map<String, String> CHANGE_TYPE_DESC_MAP = new HashMap<String, String>() {{
        put("in", "入库");
        put("out", "出库");
        put("adjust", "调整");
        put("refund", "退货");
    }};

    /**
     * 调整库存
     */
    @Transactional(rollbackFor = Exception.class)
    public void adjustStock(StockAdjustRequest request, Long operatorId) {
        // 查询商品
        Product product = productMapper.selectById(request.getProductId());
        if (product == null) {
            throw new RuntimeException("商品不存在");
        }

        // 计算调整后库存
        int beforeStock = product.getStock() != null ? product.getStock() : 0;
        int afterStock = beforeStock + request.getAdjustQuantity();

        // 库存不能为负数
        if (afterStock < 0) {
            throw new RuntimeException("库存不足，无法减少");
        }

        // 更新商品库存
        product.setStock(afterStock);
        productMapper.updateById(product);

        // 记录库存变动
        StockRecord record = new StockRecord();
        record.setProductId(request.getProductId());
        record.setChangeType("adjust");
        record.setChangeQuantity(request.getAdjustQuantity());
        record.setBeforeStock(beforeStock);
        record.setAfterStock(afterStock);
        record.setOperatorId(operatorId);
        record.setRemark(request.getRemark());
        stockRecordMapper.insert(record);
    }

    /**
     * 出库（订单销售）
     */
    @Transactional(rollbackFor = Exception.class)
    public void stockOut(Long productId, Integer quantity, Long orderId, Long operatorId) {
        // 查询商品
        Product product = productMapper.selectById(productId);
        if (product == null) {
            throw new RuntimeException("商品不存在");
        }

        // 计算库存
        int beforeStock = product.getStock() != null ? product.getStock() : 0;
        int afterStock = beforeStock - quantity;

        // 库存不足
        if (afterStock < 0) {
            throw new RuntimeException("商品【" + product.getName() + "】库存不足");
        }

        // 更新商品库存和销量
        product.setStock(afterStock);
        product.setSales((product.getSales() != null ? product.getSales() : 0) + quantity);
        productMapper.updateById(product);

        // 记录库存变动
        StockRecord record = new StockRecord();
        record.setProductId(productId);
        record.setChangeType("out");
        record.setChangeQuantity(-quantity);
        record.setBeforeStock(beforeStock);
        record.setAfterStock(afterStock);
        record.setOrderId(orderId);
        record.setOperatorId(operatorId);
        record.setRemark("订单销售");
        stockRecordMapper.insert(record);
    }

    /**
     * 入库（退货）
     */
    @Transactional(rollbackFor = Exception.class)
    public void stockRefund(Long productId, Integer quantity, Long orderId, Long operatorId, String remark) {
        // 查询商品
        Product product = productMapper.selectById(productId);
        if (product == null) {
            throw new RuntimeException("商品不存在");
        }

        // 计算库存
        int beforeStock = product.getStock() != null ? product.getStock() : 0;
        int afterStock = beforeStock + quantity;

        // 更新商品库存和销量
        product.setStock(afterStock);
        product.setSales(Math.max(0, (product.getSales() != null ? product.getSales() : 0) - quantity));
        productMapper.updateById(product);

        // 记录库存变动
        StockRecord record = new StockRecord();
        record.setProductId(productId);
        record.setChangeType("refund");
        record.setChangeQuantity(quantity);
        record.setBeforeStock(beforeStock);
        record.setAfterStock(afterStock);
        record.setOrderId(orderId);
        record.setOperatorId(operatorId);
        record.setRemark(remark != null ? remark : "退货入库");
        stockRecordMapper.insert(record);
    }

    /**
     * 入库
     */
    @Transactional(rollbackFor = Exception.class)
    public void stockIn(Long productId, Integer quantity, Long operatorId, String remark) {
        // 查询商品
        Product product = productMapper.selectById(productId);
        if (product == null) {
            throw new RuntimeException("商品不存在");
        }

        // 计算库存
        int beforeStock = product.getStock() != null ? product.getStock() : 0;
        int afterStock = beforeStock + quantity;

        // 更新商品库存
        product.setStock(afterStock);
        productMapper.updateById(product);

        // 记录库存变动
        StockRecord record = new StockRecord();
        record.setProductId(productId);
        record.setChangeType("in");
        record.setChangeQuantity(quantity);
        record.setBeforeStock(beforeStock);
        record.setAfterStock(afterStock);
        record.setOperatorId(operatorId);
        record.setRemark(remark != null ? remark : "商品入库");
        stockRecordMapper.insert(record);
    }

    /**
     * 查询库存记录
     */
    public IPage<StockRecordVO> getStockRecords(StockQueryRequest request) {
        // 构建查询条件
        LambdaQueryWrapper<StockRecord> wrapper = new LambdaQueryWrapper<>();

        // 商品ID
        if (request.getProductId() != null) {
            wrapper.eq(StockRecord::getProductId, request.getProductId());
        }

        // 变动类型
        if (StringUtils.hasText(request.getChangeType())) {
            wrapper.eq(StockRecord::getChangeType, request.getChangeType());
        }

        // 操作人
        if (request.getOperatorId() != null) {
            wrapper.eq(StockRecord::getOperatorId, request.getOperatorId());
        }

        // 日期范围
        if (StringUtils.hasText(request.getStartDate())) {
            try {
                LocalDateTime startDateTime = LocalDate.parse(request.getStartDate(), 
                    DateTimeFormatter.ISO_LOCAL_DATE).atStartOfDay();
                wrapper.ge(StockRecord::getCreateTime, startDateTime);
            } catch (Exception e) {
                // 日期格式错误，忽略
            }
        }

        if (StringUtils.hasText(request.getEndDate())) {
            try {
                LocalDateTime endDateTime = LocalDate.parse(request.getEndDate(), 
                    DateTimeFormatter.ISO_LOCAL_DATE).atTime(LocalTime.MAX);
                wrapper.le(StockRecord::getCreateTime, endDateTime);
            } catch (Exception e) {
                // 日期格式错误，忽略
            }
        }

        // 按时间降序
        wrapper.orderByDesc(StockRecord::getCreateTime);

        // 分页查询
        Page<StockRecord> page = new Page<>(request.getPage(), request.getPageSize());
        IPage<StockRecord> recordPage = stockRecordMapper.selectPage(page, wrapper);

        // 转换为VO
        IPage<StockRecordVO> voPage = recordPage.convert(this::convertToVO);

        return voPage;
    }

    /**
     * 转换为VO对象
     */
    private StockRecordVO convertToVO(StockRecord record) {
        StockRecordVO vo = new StockRecordVO();
        BeanUtils.copyProperties(record, vo);

        // 变动类型描述
        vo.setChangeTypeDesc(CHANGE_TYPE_DESC_MAP.getOrDefault(record.getChangeType(), "未知"));

        // 商品信息
        Product product = productMapper.selectById(record.getProductId());
        if (product != null) {
            vo.setProductName(product.getName());
            vo.setProductImage(product.getImage());
        }

        // 操作人信息
        User operator = userMapper.selectById(record.getOperatorId());
        if (operator != null) {
            vo.setOperatorName(operator.getName());
        }

        // 订单信息
        if (record.getOrderId() != null) {
            Order order = orderMapper.selectById(record.getOrderId());
            if (order != null) {
                vo.setOrderNo(order.getOrderNo());
            }
        }

        return vo;
    }

}

